feat(core): use shared JS box image for project containers#281
Conversation
Adding .gitkeep for PR creation (default mode). This file will be removed when the task is complete. Issue: ProverCoderAI#267
Working session summaryDone. PR #281 is updated and green: #281 Latest pushed head: Key final fix:
Verification passed locally: GitHub checks passed on PR #281, including Docker E2E: Working tree is clean. This summary was automatically extracted from the AI working session output. |
🤖 Solution Draft LogThis log file contains the complete execution trace of the AI solution draft process. 💰 Cost estimation:
📊 Context and tokens usage:
Total: (1.6M + 67.2M cached) input tokens, 125.0K output tokens, $88.495497 cost 🤖 Models used:
📎 Log file uploaded as Repository (2 chunks) (201432KB)Now working session is ended, feel free to review and add any feedback on the solution draft. |
✅ Ready to mergeThis pull request is now ready to be merged:
Monitored by hive-mind with --auto-restart-until-mergeable flag |
This reverts commit 45f4f3d.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR integrates unified ChangesContainer Image Standardization and Entrypoint Refinement
🎯 3 (Moderate) | ⏱️ ~25 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/lib/tests/core/templates.test.ts`:
- Around line 60-104: Add property-based tests (using fast-check) for the new
invariants around renderDockerfile outputs used in
packages/lib/tests/core/templates.test.ts (and the other ranges noted) instead
of only example-based assertions: write fast-check properties that call
renderDockerfile(makeTemplateConfig(arbitraryConfig)) to assert (1) refspec
exclusion invariant, (2) prompt non-interactive inertness invariant, and (3)
HOME/PATH/WORKDIR normalization invariant across generated configs (assert using
expect/contains helpers like expectContainsAll); use fast-check arbitraries for
TemplateConfig inputs, keep tests synchronous (no async/await), and put
unit-style checks using the project’s Effect test utilities where applicable
rather than raw async code.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 6bbab1ae-98b5-4847-a515-ad0643df2cd0
📒 Files selected for processing (7)
packages/app/src/lib/core/templates-entrypoint/tasks.tspackages/app/src/lib/core/templates-prompt.tspackages/app/src/lib/core/templates/dockerfile.tspackages/lib/src/core/templates-entrypoint/tasks.tspackages/lib/src/core/templates-prompt.tspackages/lib/src/core/templates/dockerfile.tspackages/lib/tests/core/templates.test.ts
| describe("renderDockerfile", () => { | ||
| it("uses the shared JS box image as the project container base", () => { | ||
| const dockerfile = renderDockerfile(makeTemplateConfig()) | ||
|
|
||
| expect(dockerfile).toContain("ARG DOCKER_GIT_BASE_IMAGE=konard/box-js:latest") | ||
| expect(dockerfile).toContain("FROM ${DOCKER_GIT_BASE_IMAGE}") | ||
| expect(dockerfile).toContain("USER root") | ||
| expect(dockerfile).not.toContain("FROM ubuntu:24.04") | ||
| }) | ||
|
|
||
| it("renames the box base user to the configured SSH user", () => { | ||
| const dockerfile = renderDockerfile(makeTemplateConfig()) | ||
|
|
||
| expect(dockerfile).toContain("for BASE_USER in box ubuntu; do") | ||
| expect(dockerfile).toContain('if [ "$BASE_USER" != "dev" ] && id -u "$BASE_USER" >/dev/null 2>&1; then') | ||
| expect(dockerfile).toContain('usermod -l dev -d /home/dev -m -s /usr/bin/zsh "$BASE_USER" || true') | ||
| }) | ||
|
|
||
| it("normalizes inherited box image HOME and workdir to the configured SSH user", () => { | ||
| const dockerfile = renderDockerfile(makeTemplateConfig()) | ||
|
|
||
| expectContainsAll(dockerfile, [ | ||
| "ENV HOME=/home/dev", | ||
| "ENV PATH=/usr/local/bun/bin:/home/dev/.deno/bin:/home/dev/.bun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", | ||
| "WORKDIR /home/dev" | ||
| ]) | ||
| }) | ||
|
|
||
| it("rewrites inherited login rc files away from the base image home", () => { | ||
| const dockerfile = renderDockerfile(makeTemplateConfig()) | ||
|
|
||
| expectContainsAll(dockerfile, [ | ||
| "find /home/dev -maxdepth 2 -type f", | ||
| '-name ".profile" -o -name ".bash_profile" -o -name ".bashrc" -o -name ".zprofile" -o -name ".zshenv" -o -name ".zshrc"', | ||
| '-exec sed -i -e "s|/home/box|/home/dev|g" -e "s|/home/ubuntu|/home/dev|g" {} +;' | ||
| ]) | ||
| }) | ||
|
|
||
| it("keeps the runtime PATH extension relative to the login shell environment", () => { | ||
| const dockerfile = renderDockerfile(makeTemplateConfig()) | ||
|
|
||
| expect(dockerfile).toContain('RUN printf "export PATH=/usr/local/bun/bin:\\$PATH\\n"') | ||
| expect(dockerfile).not.toContain('RUN printf "export PATH=/usr/local/bun/bin:$PATH\\n"') | ||
| }) | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift
Add fast-check property tests for the new invariants.
The added tests are example-based only. For these new behaviors, add fast-check properties (e.g., refspec exclusion invariant, prompt non-interactive inertness invariant, HOME/PATH normalization invariant across generated configs) to satisfy the test policy.
As per coding guidelines **/*.{test,spec}.{ts,tsx}: Property-based tests (fast-check) must verify mathematical invariants; unit tests must use Effect test utilities without async/await.
Also applies to: 125-142, 359-366
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/lib/tests/core/templates.test.ts` around lines 60 - 104, Add
property-based tests (using fast-check) for the new invariants around
renderDockerfile outputs used in packages/lib/tests/core/templates.test.ts (and
the other ranges noted) instead of only example-based assertions: write
fast-check properties that call
renderDockerfile(makeTemplateConfig(arbitraryConfig)) to assert (1) refspec
exclusion invariant, (2) prompt non-interactive inertness invariant, and (3)
HOME/PATH/WORKDIR normalization invariant across generated configs (assert using
expect/contains helpers like expectContainsAll); use fast-check arbitraries for
TemplateConfig inputs, keep tests synchronous (no async/await), and put
unit-style checks using the project’s Effect test utilities where applicable
rather than raw async code.
Summary
Fixes #267.
Switches generated project workspace Dockerfiles from a raw
ubuntu:24.04base to the sharedkonard/box-js:latestDocker Hub image published by https://github.com/link-foundation/box. The docker-git bootstrap layers, SSH entrypoint, auth bridge, host-Docker-backed runtime contract, and clone/cache orchestration remain owned by docker-git.Reproduction
Before this change,
renderDockerfile(makeTemplateConfig())emitted:FROM ubuntu:24.04and only knew how to rename an existing
ubuntuuser. That did not satisfy issue #267's requirement to reuse the shared box infrastructure, and it risked duplicate UID-1000 users when a box base already has/home/box.CI then exposed box-specific follow-up invariants:
bash -lccommands sourced/etc/profile.d/zz-prompt.sh, and the prompt script touched/dev/ttywithout a controlling TTY.konard/box-jsinheritsHOME=/home/box,WORKDIR=/home/box, and login rc files with absolute/home/boxreferences. After renamingbox -> dev,docker exec -u dev bash -lc '...'could still resolve user paths through/home/box, and login shells failed on/home/box/.deno/env.+refs/*:refs/*; on public GitHub repositories this enumeratedrefs/pull/*and timed out the login-context E2E after the cache volume was reused by the PR case.Changes
ARG DOCKER_GIT_BASE_IMAGE=konard/box-js:latestandFROM ${DOCKER_GIT_BASE_IMAGE}to generated project Dockerfiles.USER rootbefore docker-git's apt/tool/bootstrap layers so the existing setup remains valid on top of the box image.boxorubuntubase users to the configuredsshUserbefore falling back to user creation.HOME=/home/<sshUser>, a user-correct PATH, andWORKDIR /home/<sshUser>..profile,.bashrc,.zshrc, etc.) from/home/boxor/home/ubuntuto/home/<sshUser>./etc/profile.d/bun.shruntime-relative by writing\$PATHinstead of baking the base image build-time PATH.zz-prompt.shinert for non-interactive shells; interactive shells still install prompt/TTY recovery hooks.refs/heads/*andrefs/tags/*, so clone-cache reuse does not fetch every GitHub pull-request ref.packages/app/src/libfor the bundled CLI build.ghcr.io/link-foundation/box:latestcurrently fails anonymous pulls with HTTP 401, while Docker Hub is publicly pullable. Registry metadata also shows the fullkonard/box:latestamd64 manifest is about 5.6 GiB compressed, whilekonard/box-js:latestis about 1.6 GiB compressed and still comes from the same shared box infrastructure.Mathematical Guarantees
Invariants
forall config in TemplateConfig: baseImage(renderDockerfile(config)) = ${DOCKER_GIT_BASE_IMAGE}.forall config in TemplateConfig: sshUser(config) owns /home/sshUser(config)after the user-normalization block when the base image hasbox,ubuntu, or neither.forall config in TemplateConfig: HOME(renderDockerfile(config)) = /home/sshUser(config) and WORKDIR(renderDockerfile(config)) = /home/sshUser(config).forall p in loginRc(sshUser): not contains(p, "/home/box") and not contains(p, "/home/ubuntu")for inherited base-home references covered by the generated rewrite block.forall shell: nonInteractive(shell) -> source(zz-prompt.sh, shell)produces no prompt mutation and no TTY write.forall r in cloneCacheRefreshRefs: r in refs/heads/* union refs/tags/*; in particular,refs/pull/*is excluded from cache refresh.CORE -> SHELLboundary is preserved: this change modifies pure template rendering; runtime effects remain in generated shell scripts and Docker execution layers.Preconditions
DOCKER_GIT_BASE_IMAGEis Debian/Ubuntu-compatible and supports apt-based root setup./entrypoint.sh.Postconditions
bash -lcwithout prompt/TTY side effects and with~and login rc paths resolving into the mounted SSH user home.Complexity
O(1)time andO(1)additional space.O(|all remote refs|)toO(|heads| + |tags|)remote ref enumeration.Verification
bun run --cwd packages/lib test -- tests/core/templates.test.tsbun run checkbun run testbun run buildbun run lintbun run lint:effectbun run check:dist-deps-prunegit diff --checkNote: this local runner does not have the
dockerbinary installed, so local image build was not run here; Docker/E2E verification is covered by GitHub Actions on PR #281.